let fs = require("fs");
let shell = require("shelljs");
let compressing = require("compressing");
var log4js = require("log4js");

log4js.configure({
  appenders: {
    ruleConsole: { type: "console" },
    ruleFile: {
      type: "dateFile", //可以是console,dateFile,file,Logstash等
      filename: "logs/server-", //将会按照filename和pattern拼接文件名
      pattern: "yyyy-MM-dd.log",
      maxLogSize: 10 * 1000 * 1000,
      numBackups: 3,
      alwaysIncludePattern: true,
      layout: {
        type: "pattern",
        pattern:
          "时间:%d{yyyy-MM-dd hh:mm:ss,SSS}%t级别:[%p]%t消息:%m%n------------------------------------",
      },
    },
  },
  categories: {
    default: { appenders: ["ruleConsole", "ruleFile"], level: "info" },
    wifi: { appenders: ["ruleFile"], level: "all" },
  },
});
var logger = log4js.getLogger("wifi"); //获取wifi这个类别

// 结果输出目录
let outputDir = "output";

var filePath = process.argv.length === 3 ? process.argv[2] : null;

main(filePath);

/**
 * 入口函数
 */
async function main(filePath) {
  // 初始化输出目录
  init();
  // 得到所有npm包名
  let pack = require("./wait-download-packages.json");
  // 如果是命令行里传入的package.json文件，则使用指定的文件
  if (filePath) {
    if (!fileIsExsist(filePath, true)) {
      console.log("无效的package.json路径->", filePath);
      return;
    }
    pack = analysisPackageJson(filePath);
  }
  // 进入output目录
  shell.cd(outputDir);
  // 开始下载
  await start(pack);

  console.log("|-----------下载完成-----------|");
}

/**
 * 初始化输出目录
 */
function init() {
  if (!fileIsExsist(outputDir)) {
    fs.mkdirSync(outputDir);
  }
}

/**
 * 开始下载待下载的所有包
 * @param {待下载的包信息}} pack
 */
async function start(pack) {
  for (let item of pack) {
    console.log("|--开始下载-->", item);
    let name = item.packageName + "@" + item.version;
    let fileName = item.packageName + "-" + item.version + ".tgz";
    if (fileName.indexOf("@") === 0) {
      // 是以@开头的，例：@verdaccio/readme
      fileName = fileName.substring(1);
      fileName = fileName.replace("/", "-");
    }
    // 检查是否已经存在
    try {
      if (fileIsExsist(fileName)) {
        console.log(fileName + "已存在");
        logger.info(fileName + "已存在");
      } else {
        console.log(fileName + "不存在，开始下载");
        logger.info(fileName + "不存在，开始下载");
        let res = await downloadPackage(name);
        if (res) {
          // 下载成功
          // 删除package文件夹
          deleteall("./package");
          // let unexpressRes = await unexpressPackage(fileName)
          // if (unexpressRes) {
          //   console.log('解压成功')
          //   let childPackage = analysisPackageJson()
          //   await start(childPackage)
          // } else {
          //   console.log('解压失败')
          // }
        } else {
          console.log(fileName + "下载失败");
        }
      }
    } catch (e) {}
  }
}

/**
 * 文件/文件夹是否存在
 * @param {文件/文件夹} fileName
 * @returns boolean
 */
function fileIsExsist(fileName, isFullPath) {
  try {
    if (isFullPath) {
      fs.accessSync(fileName, fs.constants.F_OK);
    } else {
      fs.accessSync("./" + fileName, fs.constants.F_OK);
    }
    return true;
  } catch (e) {
    return false;
  }
}

/**
 * 删除指定文件夹
 * @param {文件路径} path
 */
function deleteall(path) {
  let files = [];
  if (fs.existsSync(path)) {
    files = fs.readdirSync(path);
    files.forEach(function (file, index) {
      // console.log(file);
      let curPath = path + "/" + file;
      console.log(curPath);
      if (fs.statSync(curPath).isDirectory()) {
        // recurse
        deleteall(curPath);
      } else {
        // delete file
        fs.unlinkSync(curPath);
      }
    });
    fs.rmdirSync(path);
  }
}

/**
 * 解析package.json文件依赖的所有包
 * @returns 需要下载的包信息
 */
function analysisPackageJson(fileName) {
  try {
    let packageJson = fileName
      ? require(fileName)
      : require("./" + outputDir + "/package/package.json");
    let dependencies = packageJson ? packageJson.dependencies : {};
    let devDependencies = packageJson ? packageJson.devDependencies : {};
    Object.assign(dependencies, devDependencies);
    let arr = [];
    for (let key in dependencies) {
      let version = dependencies[key];
      if (version.indexOf("^") === 0 || version.indexOf("~") === 0) {
        version = version.substring(1);
      }
      arr.push({ packageName: key, version: version });
    }
    return arr;
  } catch (err) {
    console.log(err.message);
    return [];
  }
}

/**
 * 解压当前目录的压缩包到当前目录
 * @param {当前目录的tgz压缩包} fileName
 * @returns
 */
function unexpressPackage(fileName) {
  try {
    return new Promise((resolve, reject) => {
      compressing.tgz
        .uncompress("./" + fileName, "./")
        .then(() => {
          resolve(true);
        })
        .catch((err) => {
          reject(false);
        });
    });
  } catch (error) {
    reject(false);
  }
}

/**
 * 下载指定的包
 * @param {包名@版本号} packageName
 * @returns
 */
function downloadPackage(packageName) {
  try {
    return new Promise((resolve, reject) => {
      shell.exec(`npm pack ${packageName}`, function (err) {
        if (err) {
          reject(false);
        } else {
          resolve(true);
        }
      });
    });
  } catch (err) {
    return false;
  }
}
